+Fri Feb 13 00:54:59 2004 Matthias Clasen <maclas@gmx.de>
+
+ Fix for #104811, Padraig O'Briain:
+
+ * gtk/gtkscale.h:
+ * gtk/gtkscale.c (_gtk_scale_clear_layout):
+ * gtk/gtkscale.c (gtk_scale_get_layout_offsets):
+ * gtk/gtkscale.c (gtk_scale_get_layout): New functions to determine the
+ text and its position from a GtkScale, to make it more accessible.
+ * gtk/gtkhscale.c (gtk_hscale_get_layout_offsets):
+ * gtk/gtkvscale.c (gtk_vscale_get_layout_offsets): Implementations of the
+ new GtkScale vfunc.
+
Thu Feb 12 17:59:52 2004 Owen Taylor <otaylor@redhat.com>
* gtk/gtkicontheme.c (gtk_icon_theme_get_search_path):
+Fri Feb 13 00:54:59 2004 Matthias Clasen <maclas@gmx.de>
+
+ Fix for #104811, Padraig O'Briain:
+
+ * gtk/gtkscale.h:
+ * gtk/gtkscale.c (_gtk_scale_clear_layout):
+ * gtk/gtkscale.c (gtk_scale_get_layout_offsets):
+ * gtk/gtkscale.c (gtk_scale_get_layout): New functions to determine the
+ text and its position from a GtkScale, to make it more accessible.
+ * gtk/gtkhscale.c (gtk_hscale_get_layout_offsets):
+ * gtk/gtkvscale.c (gtk_vscale_get_layout_offsets): Implementations of the
+ new GtkScale vfunc.
+
Thu Feb 12 17:59:52 2004 Owen Taylor <otaylor@redhat.com>
* gtk/gtkicontheme.c (gtk_icon_theme_get_search_path):
+Fri Feb 13 00:54:59 2004 Matthias Clasen <maclas@gmx.de>
+
+ Fix for #104811, Padraig O'Briain:
+
+ * gtk/gtkscale.h:
+ * gtk/gtkscale.c (_gtk_scale_clear_layout):
+ * gtk/gtkscale.c (gtk_scale_get_layout_offsets):
+ * gtk/gtkscale.c (gtk_scale_get_layout): New functions to determine the
+ text and its position from a GtkScale, to make it more accessible.
+ * gtk/gtkhscale.c (gtk_hscale_get_layout_offsets):
+ * gtk/gtkvscale.c (gtk_vscale_get_layout_offsets): Implementations of the
+ new GtkScale vfunc.
+
Thu Feb 12 17:59:52 2004 Owen Taylor <otaylor@redhat.com>
* gtk/gtkicontheme.c (gtk_icon_theme_get_search_path):
+Fri Feb 13 00:54:59 2004 Matthias Clasen <maclas@gmx.de>
+
+ Fix for #104811, Padraig O'Briain:
+
+ * gtk/gtkscale.h:
+ * gtk/gtkscale.c (_gtk_scale_clear_layout):
+ * gtk/gtkscale.c (gtk_scale_get_layout_offsets):
+ * gtk/gtkscale.c (gtk_scale_get_layout): New functions to determine the
+ text and its position from a GtkScale, to make it more accessible.
+ * gtk/gtkhscale.c (gtk_hscale_get_layout_offsets):
+ * gtk/gtkvscale.c (gtk_vscale_get_layout_offsets): Implementations of the
+ new GtkScale vfunc.
+
Thu Feb 12 17:59:52 2004 Owen Taylor <otaylor@redhat.com>
* gtk/gtkicontheme.c (gtk_icon_theme_get_search_path):
+Fri Feb 13 00:54:59 2004 Matthias Clasen <maclas@gmx.de>
+
+ Fix for #104811, Padraig O'Briain:
+
+ * gtk/gtkscale.h:
+ * gtk/gtkscale.c (_gtk_scale_clear_layout):
+ * gtk/gtkscale.c (gtk_scale_get_layout_offsets):
+ * gtk/gtkscale.c (gtk_scale_get_layout): New functions to determine the
+ text and its position from a GtkScale, to make it more accessible.
+ * gtk/gtkhscale.c (gtk_hscale_get_layout_offsets):
+ * gtk/gtkvscale.c (gtk_vscale_get_layout_offsets): Implementations of the
+ new GtkScale vfunc.
+
Thu Feb 12 17:59:52 2004 Owen Taylor <otaylor@redhat.com>
* gtk/gtkicontheme.c (gtk_icon_theme_get_search_path):
+Fri Feb 13 00:54:24 2004 Matthias Clasen <maclas@gmx.de>
+
+ * gtk/gtk-sections.txt: Add gtk_scale_get_layout
+ and gtk_scale_get_layout_offsets.
+
Thu Feb 12 23:56:12 2004 Matthias Clasen <maclas@gmx.de>
* gtk/gtk-sections.txt: Add gtk_tooltips_get_info_from_tip_window.
gtk_scale_get_digits
gtk_scale_get_draw_value
gtk_scale_get_value_pos
+gtk_scale_get_layout
+gtk_scale_get_layout_offsets
<SUBSECTION Standard>
GTK_SCALE
GTK_IS_SCALE
static gboolean gtk_hscale_expose (GtkWidget *widget,
GdkEventExpose *event);
+static void gtk_hscale_get_layout_offsets (GtkScale *scale,
+ gint *x,
+ gint *y);
+
GType
gtk_hscale_get_type (void)
{
{
GtkWidgetClass *widget_class;
GtkRangeClass *range_class;
+ GtkScaleClass *scale_class;
widget_class = GTK_WIDGET_CLASS (class);
range_class = GTK_RANGE_CLASS (class);
+ scale_class = GTK_SCALE_CLASS (class);
parent_class = g_type_class_peek_parent (class);
range_class->slider_detail = "hscale";
+
+ scale_class->get_layout_offsets = gtk_hscale_get_layout_offsets;
widget_class->expose_event = gtk_hscale_expose;
}
gtk_hscale_expose (GtkWidget *widget,
GdkEventExpose *event)
{
- GtkRange *range;
- GtkHScale *hscale;
GtkScale *scale;
- range = GTK_RANGE (widget);
scale = GTK_SCALE (widget);
- hscale = GTK_HSCALE (widget);
/* We need to chain up _first_ so the various geometry members of
* GtkRange struct are updated.
if (scale->draw_value)
{
PangoLayout *layout;
- PangoRectangle logical_rect;
- gchar *txt;
gint x, y;
GtkStateType state_type;
- gint value_spacing;
- gtk_widget_style_get (widget, "value_spacing", &value_spacing, NULL);
-
- txt = _gtk_scale_format_value (scale,
- GTK_RANGE (scale)->adjustment->value);
-
- layout = gtk_widget_create_pango_layout (widget, txt);
- g_free (txt);
-
- pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
-
- switch (scale->value_pos)
- {
- case GTK_POS_LEFT:
- x = range->range_rect.x - value_spacing - logical_rect.width;
- y = range->range_rect.y + (range->range_rect.height - logical_rect.height) / 2;
- break;
-
- case GTK_POS_RIGHT:
- x = range->range_rect.x + range->range_rect.width + value_spacing;
- y = range->range_rect.y + (range->range_rect.height - logical_rect.height) / 2;
- break;
-
- case GTK_POS_TOP:
- x = range->slider_start +
- (range->slider_end - range->slider_start - logical_rect.width) / 2;
- x = CLAMP (x, 0, widget->allocation.width - logical_rect.width);
- y = range->range_rect.y - logical_rect.height - value_spacing;
- break;
-
- case GTK_POS_BOTTOM:
- x = range->slider_start +
- (range->slider_end - range->slider_start - logical_rect.width) / 2;
- x = CLAMP (x, 0, widget->allocation.width - logical_rect.width);
- y = range->range_rect.y + range->range_rect.height + value_spacing;
- break;
-
- default:
- g_return_val_if_reached (FALSE);
- x = 0;
- y = 0;
- break;
- }
-
- x += widget->allocation.x;
- y += widget->allocation.y;
-
+ layout = gtk_scale_get_layout (scale);
+ gtk_scale_get_layout_offsets (scale, &x, &y);
+
state_type = GTK_STATE_NORMAL;
if (!GTK_WIDGET_IS_SENSITIVE (scale))
state_type = GTK_STATE_INSENSITIVE;
x, y,
layout);
- g_object_unref (layout);
}
return FALSE;
}
+
+static void
+gtk_hscale_get_layout_offsets (GtkScale *scale,
+ gint *x,
+ gint *y)
+{
+ GtkWidget *widget;
+ GtkRange *range;
+ GtkScale *scale;
+ PangoLayout *layout;
+ PangoRectangle logical_rect;
+ gint value_spacing;
+
+ widget = GTK_WIDGET (scale);
+ layout = gtk_scale_get_layout (scale);
+
+ if (!layout)
+ {
+ *x = 0;
+ *y = 0;
+
+ return;
+ }
+
+ gtk_widget_style_get (widget, "value_spacing", &value_spacing, NULL);
+
+ range = GTK_RANGE (widget);
+ scale = GTK_SCALE (widget);
+
+ pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
+
+ switch (scale->value_pos)
+ {
+ case GTK_POS_LEFT:
+ *x = range->range_rect.x - value_spacing - logical_rect.width;
+ *y = range->range_rect.y + (range->range_rect.height - logical_rect.height) / 2;
+ break;
+
+ case GTK_POS_RIGHT:
+ *x = range->range_rect.x + range->range_rect.width + value_spacing;
+ *y = range->range_rect.y + (range->range_rect.height - logical_rect.height) / 2;
+ break;
+
+ case GTK_POS_TOP:
+ *x = range->slider_start +
+ (range->slider_end - range->slider_start - logical_rect.width) / 2;
+ *x = CLAMP (*x, 0, widget->allocation.width - logical_rect.width);
+ *y = range->range_rect.y - logical_rect.height - value_spacing;
+ break;
+
+ case GTK_POS_BOTTOM:
+ *x = range->slider_start +
+ (range->slider_end - range->slider_start - logical_rect.width) / 2;
+ *x = CLAMP (*x, 0, widget->allocation.width - logical_rect.width);
+ *y = range->range_rect.y + range->range_rect.height + value_spacing;
+ break;
+
+ default:
+ g_return_val_if_reached (FALSE);
+ *x = 0;
+ *y = 0;
+ break;
+ }
+
+ *x += widget->allocation.x;
+ *y += widget->allocation.y;
+}
* unrelated code portions otherwise
*/
+#define GTK_SCALE_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_SCALE, GtkScalePrivate))
+
+typedef struct _GtkScalePrivate GtkScalePrivate;
+
+struct _GtkScalePrivate
+{
+ PangoLayout *layout;
+};
+
enum {
PROP_0,
PROP_DIGITS,
GtkStyle *previous);
static void gtk_scale_get_range_border (GtkRange *range,
GtkBorder *border);
+static void gtk_scale_finalize (GObject *object);
+static void gtk_scale_screen_changed (GtkWidget *widget,
+ GdkScreen *old_screen);
GType
gtk_scale_get_type (void)
gobject_class->set_property = gtk_scale_set_property;
gobject_class->get_property = gtk_scale_get_property;
+ gobject_class->finalize = gtk_scale_finalize;
widget_class->style_set = gtk_scale_style_set;
+ widget_class->screen_changed = gtk_scale_screen_changed;
range_class->get_range_border = gtk_scale_get_range_border;
add_slider_binding (binding_set, GDK_KP_End, 0,
GTK_SCROLL_END);
+
+ g_type_class_add_private (gobject_class, sizeof (GtkScalePrivate));
}
static void
if (scale->draw_value)
range->round_digits = digits;
+ _gtk_scale_clear_layout (scale);
gtk_widget_queue_resize (GTK_WIDGET (scale));
g_object_notify (G_OBJECT (scale), "digits");
else
GTK_RANGE (scale)->round_digits = -1;
+ _gtk_scale_clear_layout (scale);
+
gtk_widget_queue_resize (GTK_WIDGET (scale));
g_object_notify (G_OBJECT (scale), "draw_value");
{
scale->value_pos = pos;
+ _gtk_scale_clear_layout (scale);
if (GTK_WIDGET_VISIBLE (scale) && GTK_WIDGET_MAPPED (scale))
gtk_widget_queue_resize (GTK_WIDGET (scale));
range->min_slider_size = slider_length;
+ _gtk_scale_clear_layout (GTK_SCALE (widget));
+
(* GTK_WIDGET_CLASS (parent_class)->style_set) (widget, previous);
}
+static void
+gtk_scale_screen_changed (GtkWidget *widget,
+ GdkScreen *old_screen)
+{
+ _gtk_scale_clear_layout (GTK_SCALE (widget));
+}
/**
* _gtk_scale_format_value:
return g_strdup_printf ("%0.*f", scale->digits,
value);
}
+
+static void
+gtk_scale_finalize (GObject *object)
+{
+ GtkScale *scale;
+
+ g_return_if_fail (GTK_IS_SCALE (object));
+
+ scale = GTK_SCALE (object);
+
+ _gtk_scale_clear_layout (scale);
+
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+/**
+ * gtk_scale_get_layout:
+ * @scale: A #GtkScale
+ *
+ * Gets the #PangoLayout used to display the scale. The returned object
+ * is owned by the scale so does not need to be freed by the caller.
+ *
+ * Return value: the #PangoLayout for this scale, or %NULL if the draw_value property
+ * is %FALSE.
+ *
+ * Since: 2.4
+ **/
+PangoLayout *
+gtk_scale_get_layout (GtkScale *scale)
+{
+ GtkScalePrivate *priv = GTK_SCALE_GET_PRIVATE (scale);
+ gchar *txt;
+
+ g_return_val_if_fail (GTK_IS_SCALE (scale), NULL);
+
+ if (!priv->layout)
+ {
+ if (scale->draw_value)
+ priv->layout = gtk_widget_create_pango_layout (GTK_WIDGET (scale), NULL);
+ }
+
+ if (scale->draw_value)
+ {
+ txt = _gtk_scale_format_value (scale,
+ GTK_RANGE (scale)->adjustment->value);
+ pango_layout_set_text (priv->layout, txt, -1);
+ g_free (txt);
+ }
+
+ return priv->layout;
+}
+
+/**
+ * gtk_scale_get_layout_offsets:
+ * @scale: a #GtkScale
+ * @x: location to store X offset of layout, or %NULL
+ * @y: location to store Y offset of layout, or %NULL
+ *
+ * Obtains the coordinates where the scale will draw the #PangoLayout
+ * representing the text in the scale. Remember
+ * when using the #PangoLayout function you need to convert to
+ * and from pixels using PANGO_PIXELS() or #PANGO_SCALE.
+ *
+ * If the draw_value property is %FALSE, the return values are
+ * undefined.
+ *
+ * Since: 2.4
+ **/
+void
+gtk_scale_get_layout_offsets (GtkScale *scale,
+ gint *x,
+ gint *y)
+{
+ gint local_x, local_y;
+
+ g_return_val_if_fail (GTK_IS_SCALE (scale), NULL);
+
+ if (GTK_SCALE_GET_CLASS (scale)->get_layout_offsets)
+ (GTK_SCALE_GET_CLASS (scale)->get_layout_offsets) (scale, &local_x, &local_y);
+
+ if (x)
+ *x = local_x;
+
+ if (y)
+ *y = local_y;
+}
+
+void _gtk_scale_clear_layout (GtkScale *scale)
+{
+ GtkScalePrivate *priv = GTK_SCALE_GET_PRIVATE (scale);
+
+ g_return_if_fail (GTK_IS_SCALE (scale));
+
+ if (priv->layout)
+ {
+ g_object_unref (priv->layout);
+ priv->layout = NULL;
+ }
+}
+
void (* draw_value) (GtkScale *scale);
+ void (* get_layout_offsets) (GtkScale *scale,
+ gint *x,
+ gint *y);
/* Padding for future expansion */
- void (*_gtk_reserved1) (void);
void (*_gtk_reserved2) (void);
void (*_gtk_reserved3) (void);
void (*_gtk_reserved4) (void);
GtkPositionType pos);
GtkPositionType gtk_scale_get_value_pos (GtkScale *scale);
+PangoLayout *gtk_scale_get_layout (GtkScale *scale);
+void gtk_scale_get_layout_offsets (GtkScale *scale,
+ gint *x,
+ gint *y);
+void _gtk_scale_clear_layout (GtkScale *scale);
void _gtk_scale_get_value_size (GtkScale *scale,
gint *width,
gint *height);
-gchar *_gtk_scale_format_value (GtkScale *scale,
- gdouble value);
+gchar *_gtk_scale_format_value (GtkScale *scale,
+ gdouble value);
+
#ifdef __cplusplus
}
static gboolean gtk_vscale_expose (GtkWidget *widget,
GdkEventExpose *event);
+static void gtk_vscale_get_layout_offsets (GtkScale *scale,
+ gint *x,
+ gint *y);
+
GType
gtk_vscale_get_type (void)
{
{
GtkWidgetClass *widget_class;
GtkRangeClass *range_class;
+ GtkScaleClass *scale_class;
widget_class = GTK_WIDGET_CLASS (class);
range_class = GTK_RANGE_CLASS (class);
+ scale_class = GTK_SCALE_CLASS (class);
parent_class = g_type_class_peek_parent (class);
range_class->slider_detail = "vscale";
+ scale_class->get_layout_offsets = gtk_vscale_get_layout_offsets;
+
widget_class->expose_event = gtk_vscale_expose;
}
gtk_vscale_expose (GtkWidget *widget,
GdkEventExpose *event)
{
- GtkRange *range;
- GtkVScale *vscale;
GtkScale *scale;
- range = GTK_RANGE (widget);
scale = GTK_SCALE (widget);
- vscale = GTK_VSCALE (widget);
/* We need to chain up _first_ so the various geometry members of
* GtkRange struct are updated.
if (scale->draw_value)
{
PangoLayout *layout;
- PangoRectangle logical_rect;
- gchar *txt;
gint x, y;
GtkStateType state_type;
- gint value_spacing;
- gtk_widget_style_get (widget, "value_spacing", &value_spacing, NULL);
-
- txt = _gtk_scale_format_value (scale,
- GTK_RANGE (scale)->adjustment->value);
-
- layout = gtk_widget_create_pango_layout (widget, txt);
- g_free (txt);
-
- pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
-
- switch (scale->value_pos)
- {
- case GTK_POS_LEFT:
- x = range->range_rect.x - logical_rect.width - value_spacing;
- y = range->slider_start + (range->slider_end - range->slider_start - logical_rect.height) / 2;
- y = CLAMP (y, 0, widget->allocation.height - logical_rect.height);
- break;
-
- case GTK_POS_RIGHT:
- x = range->range_rect.x + range->range_rect.width + value_spacing;
- y = range->slider_start + (range->slider_end - range->slider_start - logical_rect.height) / 2;
- y = CLAMP (y, 0, widget->allocation.height - logical_rect.height);
- break;
-
- case GTK_POS_TOP:
- x = range->range_rect.x + (range->range_rect.width - logical_rect.width) / 2;
- y = range->range_rect.y - logical_rect.height - value_spacing;
- break;
-
- case GTK_POS_BOTTOM:
- x = range->range_rect.x + (range->range_rect.width - logical_rect.width) / 2;
- y = range->range_rect.y + range->range_rect.height + value_spacing;
- break;
-
- default:
- g_return_val_if_reached (FALSE);
- x = 0;
- y = 0;
- break;
- }
-
- x += widget->allocation.x;
- y += widget->allocation.y;
-
+ layout = gtk_scale_get_layout (widget);
+ gtk_scale_get_layout_offsets (widget, &x, &y);
+
state_type = GTK_STATE_NORMAL;
if (!GTK_WIDGET_IS_SENSITIVE (scale))
state_type = GTK_STATE_INSENSITIVE;
"vscale",
x, y,
layout);
-
- g_object_unref (layout);
}
return FALSE;
+
+}
+
+static void
+gtk_vscale_get_layout_offsets (GtkScale *scale,
+ gint *x,
+ gint *y)
+{
+ GtkWidget *widget;
+ GtkRange *range;
+ GtkScale *scale;
+ PangoLayout *layout;
+ PangoRectangle logical_rect;
+ gint value_spacing;
+
+ widget = GTK_WIDGET (scale);
+ layout = gtk_scale_get_layout (scale);
+
+ if (!layout)
+ {
+ *x = 0;
+ *y = 0;
+
+ return;
+ }
+
+ range = GTK_RANGE (widget);
+ scale = GTK_SCALE (widget);
+
+ gtk_widget_style_get (widget, "value_spacing", &value_spacing, NULL);
+
+ pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
+
+ switch (scale->value_pos)
+ {
+ case GTK_POS_LEFT:
+ *x = range->range_rect.x - logical_rect.width - value_spacing;
+ *y = range->slider_start + (range->slider_end - range->slider_start - logical_rect.height) / 2;
+ *y = CLAMP (*y, 0, widget->allocation.height - logical_rect.height);
+ break;
+
+ case GTK_POS_RIGHT:
+ *x = range->range_rect.x + range->range_rect.width + value_spacing;
+ *y = range->slider_start + (range->slider_end - range->slider_start - logical_rect.height) / 2;
+ *y = CLAMP (*y, 0, widget->allocation.height - logical_rect.height);
+ break;
+
+ case GTK_POS_TOP:
+ *x = range->range_rect.x + (range->range_rect.width - logical_rect.width) / 2;
+ *y = range->range_rect.y - logical_rect.height - value_spacing;
+ break;
+
+ case GTK_POS_BOTTOM:
+ *x = range->range_rect.x + (range->range_rect.width - logical_rect.width) / 2;
+ *y = range->range_rect.y + range->range_rect.height + value_spacing;
+ break;
+
+ default:
+ g_return_val_if_reached (FALSE);
+ *x = 0;
+ *y = 0;
+ break;
+ }
+
+ *x += widget->allocation.x;
+ *y += widget->allocation.y;
}
+